//
//  PPNetCustomRequest.m
//  PiPi
//
//  Created by 邓标祥 on 2020/12/15.
//  Copyright © 2020 PiPiWholseSale. All rights reserved.
//

#import "PPNetCustomRequest.h"
#import "PPNetConst.h"
#import "PPSortDictionary.h"
#import "PPSign.h"
#import "PPJsonHelper.h"
#import "PPNetError.h"
#import "PPNetCategorys.h"

//#import <NSString+QCloudSHA.h>
@implementation PPCustomRequestGeneral

+ (instancetype)sharedGeneral {
    static id sharedInstance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedInstance = [[PPCustomRequestGeneral alloc]init];
    });
    return sharedInstance;
}

+ (void)loginSuccessWithUserId:(NSString *)userId token:(NSString *)token watermark:(NSString * _Nonnull)watermark uuid:(NSString *)uuid idfa:(NSString *)idfa {
    [[[self sharedGeneral] phpGeneralParameters] addEntriesFromDictionary:@{@"user_id":userId?:@"", @"token":token?:@""}];
    
    [[[self sharedGeneral] phpGeneralHeader] setObject:watermark?:@"" forKey:@"watermark"];
    [[[self sharedGeneral] phpGeneralHeader] setObject:uuid ? : @"" forKey:@"pea-mg-uuid"];
    [[[self sharedGeneral] phpGeneralHeader] setObject:idfa ? : @"" forKey:@"pea-mg-idfaImei"];
    NSString *version = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"];
    [[[self sharedGeneral] phpGeneralHeader] setObject:version forKey:@"versionname"];
    
    [[[self sharedGeneral] javaGeneralHeader] addEntriesFromDictionary:@{@"userId":userId?:@"", @"token":token?:@"",@"pea-mg-uuid":uuid,@"pea-mg-idfaImei":idfa,@"versionname":version}];
}

+ (void)loginSuccessWithStoreId:(NSString *)storeId {
    
    [[[self sharedGeneral] phpGeneralHeader] setObject:storeId forKey:@"storeId"];
    
    [[[self sharedGeneral] javaGeneralHeader] setObject:storeId forKey:@"storeId"];
}

+ (void)clearLoginInfo{
    [[[self sharedGeneral] phpGeneralParameters] removeObjectForKey:@"user_id"];
    [[[self sharedGeneral] phpGeneralParameters] removeObjectForKey:@"token"];
    
    [[[self sharedGeneral] phpGeneralHeader] removeObjectForKey:@"watermark"];
    [[[self sharedGeneral] javaGeneralHeader] removeObjectForKey:@"watermark"];
    
    [[[self sharedGeneral] javaGeneralHeader] removeObjectForKey:@"userId"];
    [[[self sharedGeneral] javaGeneralHeader] removeObjectForKey:@"token"];
}

- (NSMutableDictionary *)phpGeneralHeader{
    if (!_phpGeneralHeader) {
        _phpGeneralHeader = [NSMutableDictionary new];
    }
    return _phpGeneralHeader;
}

- (NSMutableDictionary *)phpGeneralParameters{
    if (!_phpGeneralParameters) {
        _phpGeneralParameters = [NSMutableDictionary new];
    }
    return _phpGeneralParameters;
}

- (NSMutableDictionary *)javaGeneralHeader{
    if (!_javaGeneralHeader) {
        _javaGeneralHeader = [NSMutableDictionary new];
    }
    return _javaGeneralHeader;
}

- (NSMutableDictionary *)javaGeneralParameters{
    if (!_javaGeneralHeader) {
        _javaGeneralHeader = [NSMutableDictionary new];
    }
    return _javaGeneralHeader;
}

- (NSString *)zuulSignAppKey{
    return _zuulSignAppKey?:@"";
}
@end

/// ************************************ 全省港澳所有既分割线唯独呢条至靓仔 ************************************ ///

@interface PPPhpRequest()
@property (nonatomic, copy, nonnull) NSString *cmd;
@end

@implementation PPPhpRequest

+ (instancetype)request:(PPNetHTTPMethodType)httpMethod cmd:(NSString *)cmd param:(NSDictionary *)param{
    return [self request:httpMethod cmd:cmd param:param toClass:nil];
}

+ (instancetype)request:(PPNetHTTPMethodType)httpMethod cmd:(NSString *)cmd param:(NSDictionary *)param toClass:(Class)classModel{
    return [[PPPhpRequest alloc]initWithHTTpMethod:httpMethod path:@"/index.php?c=goods" cmd:cmd param:param key:nil toClass:classModel];
}

#pragma mark -
- (instancetype)initWithHTTpMethod:(PPNetHTTPMethodType)httpMethod
                              path:(NSString * _Nonnull)path
                               cmd:(NSString * _Nonnull)cmd
                             param:(NSDictionary * _Nullable)param
                               key:(NSString * _Nullable)key
                           toClass:(Class _Nullable)classModel{
    if (self = [super init]) {
        self.isAnalyticData = YES;
        self.requestSerializerType = PPNetRequestSerializer_raw;
        self.httpMethod = httpMethod;
        self.api = path;
        self.cmd = cmd;
        self.classModel = classModel;
        self.server = [PPCustomRequestGeneral sharedGeneral].phpHost?:@"";
        self.headers = [PPCustomRequestGeneral sharedGeneral].phpGeneralHeader;
        
        NSArray *parameter = [self getParametersWithCmd:cmd param:param];
        
        NSError *error;
        NSData *jsonEncodeParama = [NSJSONSerialization dataWithJSONObject:parameter options:NSJSONWritingPrettyPrinted error:&error];
        NSString *jsonString = [[NSString alloc] initWithData:jsonEncodeParama encoding:NSUTF8StringEncoding];
        
        self.parameters = @{@"json":jsonString?:@"",
                            @"_":@([NSDate date].timeIntervalSince1970)};
        
        if (key) {
            self.key = key;
        }else{
            self.key = cmd;
        }
    }
    return self;
}

- (NSArray *)getParametersWithCmd:(NSString *)cmd param:(NSDictionary *)param{
    NSMutableDictionary *addtion = [PPCustomRequestGeneral sharedGeneral].phpGeneralParameters;
    
    NSMutableDictionary *innerDict = [[NSMutableDictionary alloc] init];
    [innerDict setObject:cmd forKey:@"cmd"];
    if (param) {
        [innerDict addEntriesFromDictionary:param];
    }
    
    if (addtion) {
        [addtion enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
            if (!innerDict[key]) {
                innerDict[key] = obj;
            }
        }];
    }
    
    PPSortDictionary *sortDict = [PPSortDictionary defaultDictionary];
    [innerDict enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
        sortDict[key] = obj;
    }];
    NSString *urlParam = [sortDict pp_jsonStringEncoded];
    NSString *key = @"NvHOeXkrSqgMjJr8u1vta6X3qDxrDwsa";
    NSString *sign = [NSString stringWithFormat:@"%@%@", urlParam, key];
    innerDict[@"sign"] = [sign pp_md5String];
    
    return @[innerDict];
}

#pragma mark - （PHP）根据具体的业务数据结构转换数据
- (void)classModelWithResponseObject:(id)responseObject onResultBlock:(PPNetJsonResultBlock)resultBlock{
    if (responseObject) {
        if ([responseObject isKindOfClass:[NSDictionary class]]) {
            NSDictionary *cmdDict = [responseObject objectForKey:self.cmd];
            if (cmdDict) {
                if ([cmdDict isKindOfClass:[NSDictionary class]]) {
                    
                    NSNumber *statusCode = cmdDict[@"statusCode"]?:@(PPNetError_unknown);
                    if (![statusCode isKindOfClass:NSString.class] &&
                        ![statusCode isKindOfClass:NSNumber.class]) {
                        resultBlock(nil, [PPNetError errorWithCode:PPNetError_formatError]);
                        return;
                    }
                    
                    if (statusCode.intValue == 0) {
                        id data = cmdDict[@"data"];
                        
                        if (data) {
                            
                            if (!self.classModel) {
                                resultBlock(data, nil);
                                return;
                            }
                            
                            if ([data isKindOfClass:[NSDictionary class]]) {
                                if ([self.classModel isSubclassOfClass:[NSDictionary class]]) {
                                    resultBlock(data, nil);
                                    return;
                                }
                                
                                id model = [PPJsonHelper modelWithData:data toClass:self.classModel];
                                if (model && [model isKindOfClass:self.classModel]) {
                                    resultBlock(model, nil);
                                }else{
                                    resultBlock(nil, [PPNetError errorWithCode:PPNetError_converError]);
                                }
                                
                            }else if ([data isKindOfClass:[NSArray class]]){
                                
                                NSArray *modelArray = [PPJsonHelper modelArrayWithData:data toClass:self.classModel];
                                if (modelArray && [modelArray isKindOfClass:[NSArray class]]) {
                                    resultBlock(modelArray, nil);
                                }else{
                                    resultBlock(nil, [PPNetError errorWithCode:PPNetError_converError]);
                                }
                                
                            }else if ([data isKindOfClass:[NSNull class]]){
                                resultBlock(nil, [PPNetError errorWithCode:PPNetError_emptyData]);
                            }else{
                                resultBlock(data, nil);
                            }
                            
                        }else{
                            //data为空
                            resultBlock(nil, [PPNetError errorWithCode:PPNetError_emptyData]);
                        }
                        
                    } else {
                        resultBlock(nil, [PPNetError errorWithCode:statusCode.integerValue message:cmdDict[@"errorMsg"]]);
                    }
                    
                }else{
                    resultBlock(nil, [PPNetError errorWithCode:PPNetError_formatError]);
                }
                
            }else{
                resultBlock(nil, [PPNetError errorWithCode:PPNetError_emptyData]);
            }
            
        }else{
            resultBlock(nil, [PPNetError errorWithCode:PPNetError_formatError]);
        }
    }else{
        //空数据
        resultBlock(nil, [PPNetError errorWithCode:PPNetError_emptyData]);
    }
}

@end

/// ************************************ 全省港澳所有既分割线唯独呢条至靓仔 ************************************ ///

@implementation PPJavaRequest

+ (instancetype)request:(PPNetHTTPMethodType)httpMethod
                   path:(NSString * _Nonnull)path
                  param:(NSDictionary * _Nullable)param{
    return [self request:httpMethod path:path param:param toClass:nil];
}

+ (instancetype)request:(PPNetHTTPMethodType)httpMethod path:(NSString *)path param:(NSDictionary *)param toClass:(Class)classModel{
    return [[PPJavaRequest alloc]initWithHTTpMethod:httpMethod path:path param:param key:nil toClass:classModel];
}

- (instancetype)initWithHTTpMethod:(PPNetHTTPMethodType)httpMethod
                              path:(NSString * _Nonnull)path
                             param:(NSDictionary * _Nullable)param
                               key:(NSString * _Nullable)key
                           toClass:(Class _Nullable)classModel{
    if (self = [super init]) {
        self.isAnalyticData = YES;
        self.requestSerializerType = PPNetRequestSerializer_json;
        self.httpMethod = httpMethod;
        self.server = [PPCustomRequestGeneral sharedGeneral].javaHost?:@"";
        self.parameters = param;
        self.classModel = classModel;
        self.api = path;
        
        self.headers = [self getHeader];
        
        if (key) {
            self.key = key;
        }else{
            self.key = path;
        }
    }
    return self;
}

- (NSMutableDictionary *)getHeader {
    NSMutableDictionary *headers = [NSMutableDictionary new];
    [headers setObject:@"application/json;charset=utf-8" forKey:@"Content-Type"];
    
    if ([PPCustomRequestGeneral sharedGeneral].javaGeneralHeader.count) {
        [headers addEntriesFromDictionary:[PPCustomRequestGeneral sharedGeneral].javaGeneralHeader];
    }
    
    NSInteger timestamp = (NSInteger)[[NSDate date] timeIntervalSince1970] - [PPCustomRequestGeneral sharedGeneral].timestampDiff;
    // 时间戳  当前时间 - 时间差值
    NSString *timestampString = [NSString stringWithFormat:@"%ld", (long)timestamp];
    // 32位随机数
    NSString *nonce = [NSString getRandomStringWithNum:32];
    // 生成签名
    NSString *sign = [self generateSignWithAlg:@"md5" appId:@"ios" appKey:[PPCustomRequestGeneral sharedGeneral].zuulSignAppKey nonce:nonce timestamp:timestampString];
    
    NSDictionary *signHeaderParam = @{
        @"pea-mg-appId":@"ios",
        @"pea-mg-alg":@"md5",
        @"pea-mg-version":@"1.0",
        @"pea-mg-timestamp":timestampString,
        @"pea-mg-nonce":nonce,
        @"pea-mg-sign" : sign 
    };
    
    [headers addEntriesFromDictionary:signHeaderParam];
    
    return headers;
}


- (NSString *)generateSignWithAlg:(NSString *)alg appId:(NSString *)appId appKey:(NSString *)appKey nonce:(NSString *)nonce timestamp:(NSString *)timestamp{
    NSString *digestValue = [NSString stringWithFormat:@"%@%@%@%@", nonce, appId, appKey, timestamp];
    NSString *signValue = @"";
    if ([alg isEqualToString:@"md5"]) {
        signValue = [NSString hmacMD5:appKey data:digestValue];

    }
    return signValue?:@"";
}



- (NSString *)getParamSignString {
    NSDictionary *dict = @{@"time":@([NSDate date].timeIntervalSince1970)};
    NSString *parameters = [PPSign createParamters:dict];
    NSString *sign = [PPSign createSign:dict];
    NSData *data = [parameters dataUsingEncoding:NSUTF8StringEncoding];
    NSString *base64Parameters = [data base64EncodedStringWithOptions:0];
    NSString *result = [NSString stringWithFormat:@"?parameters=%@&sign=%@", base64Parameters, sign];
    return result;
}


#pragma mark - （Java）根据具体的业务数据结构转换数据
- (void)classModelWithResponseObject:(id)responseObject onResultBlock:(PPNetJsonResultBlock)resultBlock{
    if (responseObject) {
        if ([responseObject isKindOfClass:[NSDictionary class]]) {
            
            NSNumber *statusCode = responseObject[@"code"]?:@(PPNetError_unknown);
            if (![statusCode isKindOfClass:NSString.class] &&
                ![statusCode isKindOfClass:NSNumber.class]) {
                resultBlock(nil, [PPNetError errorWithCode:PPNetError_formatError]);
                return;
            }
            if (statusCode.intValue == 200) {
                id data = responseObject[@"data"];
                if (data) {
                    
                    if (!self.classModel) {
                        resultBlock(data, nil);
                        return;
                    }
                    
                    
                    if ([data isKindOfClass:[NSDictionary class]]) {
                        if ([self.classModel isSubclassOfClass:[NSDictionary class]]) {
                            resultBlock(data, nil);
                            return;
                        }
                        
                        id model = [PPJsonHelper modelWithData:data toClass:self.classModel];
                        if (model && [model isKindOfClass:self.classModel]) {
                            resultBlock(model, nil);
                        }else{
                            resultBlock(nil, [PPNetError errorWithCode:PPNetError_converError]);
                        }
                        
                    }else if ([data isKindOfClass:[NSArray class]]){
                        
                        NSArray *modelArray = [PPJsonHelper modelArrayWithData:data toClass:self.classModel];
                        if (modelArray && [modelArray isKindOfClass:[NSArray class]]) {
                            resultBlock(modelArray, nil);
                        }else{
                            resultBlock(nil, [PPNetError errorWithCode:PPNetError_converError]);
                        }
                        
                    }else if ([data isKindOfClass:[NSNull class]]){
                        resultBlock(nil, [PPNetError errorWithCode:PPNetError_emptyData]);
                    }else{
                        resultBlock(data, nil);
                    }
                    
                }else{
                    //data为空
                    resultBlock(nil, [PPNetError errorWithCode:PPNetError_emptyData]);
                }
                
            } else {
                resultBlock(nil, [PPNetError errorWithCode:statusCode.integerValue message:responseObject[@"message"]]);
            }
            
        }else{
            resultBlock(nil, [PPNetError errorWithCode:PPNetError_formatError]);
        }
    }else{
        resultBlock(nil, [PPNetError errorWithCode:PPNetError_emptyData]);
    }
}
@end







#import <CommonCrypto/CommonHMAC.h>
@implementation NSString (PPNetRequest)

//Hmac加密；
+(NSString *)hmacMD5:(NSString *)key data:(NSString *)data{
    const char *keyData = key.UTF8String;
    const char *strData = data.UTF8String;
    uint8_t buffer[CC_MD5_DIGEST_LENGTH];
    CCHmac(kCCHmacAlgMD5, keyData, strlen(keyData), strData, strlen(strData), buffer);
    
    NSData *HMAC = [[NSData alloc] initWithBytes:buffer length:CC_MD5_DIGEST_LENGTH];
    NSString *result = @"";
    if (HMAC) {
        result = [HMAC base64EncodedStringWithOptions:0];
    }
    return result?:@"";
}


+ (NSString *)getRandomStringWithNum:(NSInteger)num{
    NSString *string = [[NSString alloc]init];
    for (int i = 0; i < num; i++) {
        int number = arc4random() % 36;
        if (number < 10) {
            int figure = arc4random() % 10;
            NSString *tempString = [NSString stringWithFormat:@"%d", figure];
            string = [string stringByAppendingString:tempString];
        }else {
            int figure = (arc4random() % 26) + 97;
            char character = figure;
            NSString *tempString = [NSString stringWithFormat:@"%c", character];
            string = [string stringByAppendingString:tempString];
        }
    }
    return string;
}

@end
